#include "../include/TcpConnection.hpp"
#include "../include/EventLoop.hpp"
#include <string.h>
#include <sstream>
#include <iostream>
using std::ostringstream;
namespace wd{

TcpConnection::TcpConnection(int netfd, EventLoop * loop)
:_sock(netfd)
,_localAddr(getLocalAddress())
,_peerAddr(getPeerAddress())
,_sockIO(netfd)
,_loop(loop)
{

}

void TcpConnection::send(const string& msg){
    if(msg.size() > 0)
        _sockIO.sendn(msg.c_str(), msg.size());

}

string TcpConnection::receive(){
    char buff[65536] = {0};//在栈上设置的64KB空间
    int ret = _sockIO.readline(buff, sizeof(buff));
    //设置第二个参数ret,是为了防止字符串内容中间有'\0'
    return string(buff, ret);

}

string TcpConnection::toString(){
    std::ostringstream oss;
    oss << "tcp " << _localAddr.ip() << ":" << _localAddr.port()
        << " -> " << _peerAddr.ip() << ":" << _peerAddr.port(); 
    return oss.str();

}

void TcpConnection::shutdowd(){
    _sock.shutdowdWrite();
}

InetAddress TcpConnection::getLocalAddress(){
   struct sockaddr_in addr;
   memset(&addr,0,sizeof(addr));
   socklen_t len = sizeof(addr);
   int ret = getsockname(_sock.fd(),(struct sockaddr*)&addr,&len);
   if(ret < 0){
       perror("getsockname");
   }

   return InetAddress(addr);
   
}

InetAddress TcpConnection::getPeerAddress(){
   struct sockaddr_in addr;
   memset(&addr,0,sizeof(addr));
   socklen_t len = sizeof(addr);
   int ret = getpeername(_sock.fd(),(struct sockaddr*)&addr,&len);
   if(ret < 0){
       perror("getsockname");
   }

   return InetAddress(addr);

}

bool TcpConnection::isClosed(){
    char buff[20] ={0};
    printf("%lu----closed---\n",sizeof(buff));
    return _sockIO.recvPeek(buff, sizeof(buff)) == 0;

}


void TcpConnection::handleNewConnectionCallback(){
    if(_onConnection){
        _onConnection(shared_from_this());
    }
}

void TcpConnection::handleMessageCallback(){
    if(_onMessage){
        _onMessage(shared_from_this());
    }

}

void TcpConnection::handleCloseCallback(){
    if(_onClose){
        _onClose(shared_from_this());
    }

}

void TcpConnection::sendInLoop(const string &msg){
    if(_loop){
        _loop->runInLoop(std::bind(&TcpConnection::send,this,msg));
    }    

}

int TcpConnection::readPacket(Packet & packet){
    return  _sockIO.readPacket(packet);
}

void TcpConnection::sendInLoop(const TLV& tlv){

    //tlv结构体的总长度
    int tlvlen = 8 + tlv.length;

    string msg;

    //将tlv装换成string后调用sendInLoop(const string msg)发送消息
    msg.assign((const char*)&tlv,tlvlen); 
    sendInLoop(msg);
}


}
